package social.server.main;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

import social.server.Exceptions.AlreadyDeclaredInterestException;
import social.server.Exceptions.CantRegisterInterestOwnerItem;
import social.server.Exceptions.InvalidInterestExeption;
import social.server.historicActivity.HistoricManager;

public class Item {

	private boolean available;
	private String name;
	private String description;
	private ArrayList<User> pending = new ArrayList<User>();
	private String idItem;
	private String ownerLogin;
	private ArrayList<String> category = new ArrayList<String>();
	private String requestingLogin = null;
	private Date date = null;

	/**
	 * Construtor da classe Item.
	 * 
	 * @param ownerLogin
	 *            login do dono do item
	 * @param name
	 *            nome do item
	 * @param description
	 *            descricao do item.
	 * @param category
	 *            categoria(s) do item.
	 */
	public Item(String ownerLogin, String name, String description,
			String category) {
		this.name = name;
		this.description = description;
		this.ownerLogin = ownerLogin;
		this.idItem = this.ownerLogin + "/" + Integer.toString(generateCode());
		available = true;
		date = new Date();
		String[] categories = category.split(", ");
		for (int i = 0; i < categories.length; i++) {
			this.category.add(categories[i].toLowerCase());
		}
	}

	/**
	 * 
	 * @return retorna o login da requisicao
	 */
	public String getRequestingLogin() {
		return requestingLogin;
	}

	/**
	 * 
	 * @param requestingLogin
	 *            modifica o login da requisicao
	 */
	public void setRequestingLogin(String requestingLogin) {
		this.requestingLogin = requestingLogin;
	}

	/**
	 * 
	 * @return o login do dono
	 */
	public String getOwner() {
		return ownerLogin;
	}

	/**
	 * 
	 * @param loginOwner
	 *            modifica o login do dono
	 */
	public void setOwner(String loginOwner) {
		this.ownerLogin = loginOwner;
	}

	/**
	 * 
	 * @return retorn o id do item
	 */
	public String getIdItem() {
		return idItem;
	}

	/**
	 * 
	 * @return retorna nome do item
	 */
	public String getName() {
		return name;
	}

	/**
	 * 
	 * @return retorna a descriçao do item
	 */
	public String getDescription() {
		return description;
	}

	/**
	 * modifica o estado de disponibilidade do item
	 */
	public void changeState() {
		if (checkState()) {
			available = false;
		} else {
			available = true;
		}
	}

	/**
	 * 
	 * @return checa o estado de disponibilidade do item
	 */
	public boolean checkState() {
		return available;
	}

	/**
	 * 
	 * @param user
	 *            adiciona um usuario interessado na lista de pendencias
	 */
	public void addInList(User user) {
		pending.add(user);
	}

	/**
	 * 
	 * @param user
	 *            remove o usuario da lista de pendencias
	 */
	public void removeFromList(User user) {
		pending.remove(user);
	}

	/**
	 * 
	 * @return retorna a(s) categoria(s) do item.
	 */
	public ArrayList<String> getCategory() {
		return category;
	}

	/**
	 * 
	 * @return gera o codigo do item
	 */
	private int generateCode() {
		int cont;
		int num;
		do {
			cont = 0;
			List<Integer> codeList = System.getInstance().getRequestCodeList();
			Random rand = new Random();
			num = rand.nextInt();
			if (num < 0)
				num *= -1;
			if (codeList.size() == 0) {
				System.getInstance().addRequestCodeList(num);
			} else {
				for (int i = 0; i < codeList.size(); i++) {
					if (codeList.get(i) == num) {
						++cont;
						break;
					}
				}
			}

		} while (cont != 0);

		System.getInstance().addRequestCodeList(num);
		return num;

	}

	/**
	 * 
	 * @return retorn a data
	 */
	public Date getDate() {
		return date;
	}

	/**
	 * modifica o estado de disponibilidade do item para true apos isso a lista
	 * de pendencias se esvazia novamente
	 */
	public void setTrue() {
		this.available = true;
		this.pending = new ArrayList<User>();
	}

	@Override
	public boolean equals(Object object) {
		if (!(object instanceof Item)) {
			return false;
		}
		Item item = (Item) object;
		if (item.getIdItem().equals(idItem))
			return true;
		else
			return false;
	}

	/**
	 * adiciona pessoas a lista de pessoas interessadas no item
	 * 
	 * @param user
	 * @throws Exception
	 */
	public void declareInterest(User user) throws Exception {
		if (!checkState() && !user.getLogin().equals(getOwner())
				&& !inPending(user)) {
			pending.add(user);
			HistoricManager.interestItemToHistoric(user.getLogin(), getName(),
					System.getInstance().getUser(getOwner()).getName());
		} else if (inPending(user)) {
			throw new AlreadyDeclaredInterestException();
		} else if (user.getLogin().equals(getOwner())) {
			throw new CantRegisterInterestOwnerItem();
		} else {
			throw new InvalidInterestExeption();
		}

	}

	/**
	 * verifica se o usuario ja esta na lista de pendencias
	 * 
	 * @param user
	 * @return
	 */
	public boolean inPending(User user) {

		for (User c : pending) {
			if (c.getLogin().equals(user.getLogin())) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Compara duas datas tomando como parametros datas pertencentes a classe
	 * "Date".
	 * 
	 * @param date
	 *            Primeira data passada como parametro.
	 * @return True se a data do item for maior, false caso contrario.
	 */
	public boolean compareDates(Date dateItem) {
		if (date.compareTo(dateItem) < 0) {
			return false;
		}
		return true;
	}

	/**
	 * Compara reputacoes de usuarios tomando como parametro itens dos usuarios.
	 * 
	 * @param item1
	 *            Primeiro item passado como parametro.
	 * @param item2
	 *            Segundo item passado como parametro.
	 * @return True se a primeira reputacao for maior, false caso contrario.
	 * @throws Exception
	 *             Lanca excecao ao usar outros metodos.
	 */
	public boolean compareReputations(Item item) throws Exception {
		if (System.getInstance().getUser(getOwner()).getReputation() > System
				.getInstance().getUser(item.getOwner()).getReputation()) {
			return true;
		}
		return false;
	}

}
